## 第11课 循线智能车

### （1）项目介绍：

前面我们详细的介绍了画地为牢智能车的实现方法。在这里我们可以结合前面课程中知识制作一个循迹智能车。实验中，我们还是通过循迹传感器检测智能车底部是否存在黑线，然后根据检测结果控制两个电机的转动，从而控制智能车沿着黑线行走。

### （2）流程图：

循迹智能车具体逻辑如下表格。

| 检测 | 中循迹传感器 | 中循迹传感器 | 检测到黑线：高电平 | 检测到黑线：高电平 |
| --- | --- | --- | --- | --- |
| 检测 | 中循迹传感器 | 中循迹传感器 | 检测到白线：低电平 | 检测到白线：低电平 |
| 检测 | 左循迹传感器 | 左循迹传感器 | 检测到黑线：高电平 | 检测到黑线：高电平 |
| 检测 | 左循迹传感器 | 左循迹传感器 | 检测到白线：低电平 | 检测到白线：低电平 |
| 检测 | 右循迹传感器 | 右循迹传感器 | 检测到黑线：高电平 | 检测到黑线：高电平 |
| 检测 | 右循迹传感器 | 右循迹传感器 | 检测到白线：低电平 | 检测到白线：低电平 |
| 条件 | 条件 | 条件 | 条件 | 状态 |
| 中循迹传感器检测到黑线 | 中循迹传感器检测到黑线 | 左循迹传感器检测到黑线并且 右循迹传感器检测到白线 | 左循迹传感器检测到黑线并且 右循迹传感器检测到白线 | 左旋转（PWM设为200） |
| 中循迹传感器检测到黑线 | 中循迹传感器检测到黑线 | 左循迹传感器检测到白线并且 右循迹传感器检测到黑线 | 左循迹传感器检测到白线并且 右循迹传感器检测到黑线 | 右旋转（PWM设为200） |
| 中循迹传感器检测到黑线 | 中循迹传感器检测到黑线 | 左循迹传感器检测到白线并且 右循迹传感器检测到白线 | 左循迹传感器检测到白线并且 右循迹传感器检测到白线 | 前进 |
| 中循迹传感器检测到黑线 | 中循迹传感器检测到黑线 | 左循迹传感器检测到黑线并且右循迹传感器检测到黑线 | 左循迹传感器检测到黑线并且右循迹传感器检测到黑线 | 前进 |
| 中循迹传感器检测到白线 | 中循迹传感器检测到白线 | 左循迹传感器检测到黑线并且 右循迹传感器检测到白线 | 左循迹传感器检测到黑线并且 右循迹传感器检测到白线 | 左旋转（PWM设为200） |
| 中循迹传感器检测到白线 | 中循迹传感器检测到白线 | 左循迹传感器检测到白线并且 右循迹传感器检测到黑线 | 左循迹传感器检测到白线并且 右循迹传感器检测到黑线 | 右旋转（PWM设为200） |
| 中循迹传感器检测到白线 | 中循迹传感器检测到白线 | 左循迹传感器检测到白线并且 右循迹传感器检测到白线 | 左循迹传感器检测到白线并且 右循迹传感器检测到白线 | 停止 |
| 中循迹传感器检测到白线 | 中循迹传感器检测到白线 | 左循迹传感器检测到黑线并且右循迹传感器检测到黑线 | 左循迹传感器检测到黑线并且右循迹传感器检测到黑线 | 停止 |

按照前面思路设计好智能车后，我们就需要按照设计思路开始制作智能车。我们需要设计对应的接线，测试代码，然后接线上传代码，运行，确保智能车能够实现理想中的功能。

### （3）接线图：

**巡线模块+电机**

![](media/image1.png)

接线注意：用导线把循迹模块连接到电机驱动扩展板上P1接口的G、V、D11、D7、D8；(M1、M2)和(M3、M4)两对时电机分别对应的连接到电机驱动扩展板上的接口B和接口A，电源接到BAT接口。

### （4）测试代码：

**示例代码 1（KE0165_11.ino）：**

```cpp
/*
  keyes 4WD 多功能智能车
  课程 11
  线路跟踪机器人
  http://www.keyes-robot.com
*/

const int L_PIN = 11;     // 左边传感器引脚
const int M_PIN = 7;      // 中间传感器引脚
const int R_PIN = 8;      // 右边传感器引脚
const int MA = 2;         // 电机A方向控制引脚
const int PWMA = 6;       // 电机A速度控制引脚
const int MB = 4;         // 电机B方向控制引脚
const int PWMB = 5;       // 电机B速度控制引脚

int lVal, mVal, rVal;

/* 功能：小车前进 */
void advance() {
  digitalWrite(MA, HIGH);          // 电机A正转
  analogWrite(PWMA, 150);          // 电机A速度为150
  digitalWrite(MB, HIGH);          // 电机B正转
  analogWrite(PWMB, 150);          // 电机B速度为150
}

/* 功能：小车后退 */
void back() {
  digitalWrite(MA, LOW);           // 电机A反转
  analogWrite(PWMA, 150);          // 电机A速度为150
  digitalWrite(MB, LOW);           // 电机B反转
  analogWrite(PWMB, 150);          // 电机B速度为150
}

/* 功能：小车左转 */
void turnLeft() {
  digitalWrite(MA, HIGH);          // 电机A正转
  analogWrite(PWMA, 150);          // 电机A速度为150
  digitalWrite(MB, LOW);           // 电机B反转
  analogWrite(PWMB, 150);          // 电机B速度为150
}

/* 功能：小车右转 */
void turnRight() {
  digitalWrite(MA, LOW);           // 电机A反转
  analogWrite(PWMA, 150);          // 电机A速度为150
  digitalWrite(MB, HIGH);          // 电机B正转
  analogWrite(PWMB, 150);          // 电机B速度为150
}

/* 功能：小车停止 */
void stopCar() {
  analogWrite(PWMA, 0);            // 电机A速度为0
  analogWrite(PWMB, 0);            // 电机B速度为0
}

void setup() {
  Serial.begin(9600);              // 设置波特率为9600
  pinMode(L_PIN, INPUT);           // 左边传感器引脚配置为输入模式
  pinMode(M_PIN, INPUT);           // 中间传感器引脚配置为输入模式
  pinMode(R_PIN, INPUT);           // 右边传感器引脚配置为输入模式
  pinMode(MA, OUTPUT);             // 电机A方向引脚配置为输出模式
  pinMode(PWMA, OUTPUT);           // 电机A速度引脚配置为输出模式
  pinMode(MB, OUTPUT);             // 电机B方向引脚配置为输出模式
  pinMode(PWMB, OUTPUT);           // 电机B速度引脚配置为输出模式
}

void loop() {
  lVal = digitalRead(L_PIN);       // 读取左边传感器的值
  mVal = digitalRead(M_PIN);       // 读取中间传感器的值
  rVal = digitalRead(R_PIN);       // 读取右边传感器的值

  if (mVal == 1) {                 // 中间检测到黑线
    if (lVal == 1 && rVal == 0) { // 左边检测到黑线，右边没有，左转
      turnLeft();
    } 
    else if (lVal == 0 && rVal == 1) { // 右边检测到黑线，左边没有，右转
      turnRight();
    } 
    else {                        // 其他情况前进
      advance();
    }
  } 
  else {                          // 中间未检测到黑线
    if (lVal == 1 && rVal == 0) { // 左边检测到黑线，右边没有，左转
      turnLeft();
    } 
    else if (lVal == 0 && rVal == 1) { // 右边检测到黑线，左边没有，右转
      turnRight();
    } 
    else {                        // 其他情况停止
      stopCar();
    }
  }
}
```



### （5）测试结果：

将驱动扩展板堆叠在UNO R3板上，上传好代码，按照接线图接线，将拨码开关拨至ON端后，智能车能够沿着黑线行走。

